﻿
namespace TestFsRx

open System
open System.Reactive
open System.Reactive.Linq
open FSharp.Reactive
open NUnit.Framework
open FsUnit
open TestHelpers

[<TestFixture>]
type ErrorCatch()=
    
    // if no error handler is specified in the observer
    // then the exception will be thrown out
    [<Test>]
    member this.NoErrorHandler() =

        (fun() ->
            let stream = Observable.Throw<int>(new InvalidOperationException("test"))
            stream.Subscribe ignore |> ignore)
        |> should throw typeof<InvalidOperationException>

    [<Test>]
    member this.CatchAnyExceptions() =
        let countPreError,countPostError = 8,9
        let errorStream = makeErrorStream<int,InvalidOperationException>()

        // ------------------ without Catch
        countPreError
        |> Observable.range 1
        |> Observable.concat errorStream
        |> shouldObserve countPreError true false

        // ------------------ with Catch
        countPreError
        |> Observable.range 2
        |> Observable.concat errorStream
        |> Observable.catch (Observable.Range(1,countPostError))
        |> shouldObserve (countPreError + countPostError) false true

    [<Test>]
    member this.CatchCertainError() =

        let stream = 
            Observable.Return 1
            |> Observable.concat (Observable.Throw<int>(new TimeoutException("test")))
        let catchFunc = Func<_,IObservable<int>>(fun _ -> Observable.Return 100)

        // ------------- catch the exact exception
        stream.Catch<int,TimeoutException>(catchFunc)
        |> shouldObserve 2 false true

        // ------------- what to catch is different from what to throw
        stream.Catch<int,ArgumentException>(catchFunc)
        |> shouldObserve 1 true false

    [<Test>]
    member this.OnlySwitchOnError()=
        let stream1 = [|1;2|].ToObservable()
        let stream2 = [|3;4|].ToObservable()

        stream1
        |> Observable.concat (Observable.Throw<int>(new InvalidOperationException("test")))
        |> Observable.catch stream2
        |> shouldObserve 4 false true

        stream1
        |> Observable.catch stream2
        |> Observable.toEnumerable
        |> should equal [|1;2|]




